// Generated file

// clang-format off
const char *g_detail_gather_hits_shader =
"#version 450\n"
"\n"
"// Takes a mesh and a list of tiles, where each tile corresponds to a cubic cell of the mesh.\n"
"// Each cell may contain a few triangles of the mesh,\n"
"// and tiles are oriented with an axis such that they are facing as much triangles as possible.\n"
"// We cast a ray from each pixel of each tile to triangles, to find world-space positions.\n"
"// Hit positions and triangle indices will be used to evaluate voxel data at these positions,\n"
"// which will in turn be used to bake a texture.\n"
"\n"
"layout (local_size_x = 4, local_size_y = 4, local_size_z = 4) in;\n"
"\n"
"layout (set = 0, binding = 0, std430) restrict readonly buffer MeshVertices {\n"
"	vec3 data[];\n"
"} u_vertices;\n"
"\n"
"layout (set = 0, binding = 1, std430) restrict readonly buffer MeshIndices {\n"
"	int data[];\n"
"} u_indices;\n"
"\n"
"layout (set = 0, binding = 2, std430) restrict readonly buffer CellTris {\n"
"	// List of triangle indices.\n"
"	// Grouped in chunks corresponding to triangles within a tile.\n"
"	// Each chunk can have up to 5 triangle indices.\n"
"	int data[];\n"
"} u_cell_tris;\n"
"\n"
"layout (set = 0, binding = 3, std430) restrict readonly buffer AtlasInfo {\n"
"	// [tile index] => cell info\n"
"	// X:\n"
"	// Packed 8-bit coordinates of the cell.\n"
"	// Y:\n"
"	// aaaaaaaa aaaaaaaa aaaaaaaa 0bbb00cc\n"
"	// a: 24-bit index into `u_cell_tris.data` array.\n"
"	// b: 3-bit number of triangles.\n"
"	// c: 2-bit projection direction (0:X, 1:Y, 2:Z)\n"
"	// Global invocation X and Y tell which pixel we are in.\n"
"	ivec2 data[];\n"
"} u_tile_data;\n"
"\n"
"layout (set = 0, binding = 4, std430) restrict readonly buffer Params {\n"
"	vec3 block_origin_world;\n"
"	// How big is a pixel of the atlas in world space\n"
"	float pixel_world_step;\n"
"	int tile_size_pixels;\n"
"} u_params;\n"
"\n"
"layout (set = 0, binding = 5, std430) restrict writeonly buffer HitBuffer {\n"
"	// X, Y, Z is hit position\n"
"	// W is integer triangle index\n"
"	// Index is `pixel_pos_in_tile.x + pixel_pos_in_tile.y * tile_resolution + tile_index * (tile_resolution ^ 2)`\n"
"	vec4 positions[];\n"
"} u_hits;\n"
"\n"
"const int TRI_NO_INTERSECTION = 0;\n"
"const int TRI_PARALLEL = 1;\n"
"const int TRI_INTERSECTION = 2;\n"
"\n"
"int ray_intersects_triangle(vec3 p_from, vec3 p_dir, vec3 p_v0, vec3 p_v1, vec3 p_v2, out float out_distance) {\n"
"	const vec3 e1 = p_v1 - p_v0;\n"
"	const vec3 e2 = p_v2 - p_v0;\n"
"	const vec3 h = cross(p_dir, e2);\n"
"	const float a = dot(e1, h);\n"
"\n"
"	if (abs(a) < 0.00001) {\n"
"		out_distance = -1.0;\n"
"		return TRI_PARALLEL;\n"
"	}\n"
"\n"
"	const float f = 1.0f / a;\n"
"\n"
"	const vec3 s = p_from - p_v0;\n"
"	const float u = f * dot(s, h);\n"
"\n"
"	if ((u < 0.0) || (u > 1.0)) {\n"
"		out_distance = -1.0;\n"
"		return TRI_NO_INTERSECTION;\n"
"	}\n"
"\n"
"	const vec3 q = cross(s, e1);\n"
"\n"
"	const float v = f * dot(p_dir, q);\n"
"\n"
"	if ((v < 0.0) || (u + v > 1.0)) {\n"
"		out_distance = -1.0;\n"
"		return TRI_NO_INTERSECTION;\n"
"	}\n"
"\n"
"	// At this stage we can compute t to find out where\n"
"	// the intersection point is on the line.\n"
"	const float t = f * dot(e2, q);\n"
"\n"
"	if (t > 0.00001) { // ray intersection\n"
"		//r_res = p_from + p_dir * t;\n"
"		out_distance = t;\n"
"		return TRI_INTERSECTION;\n"
"\n"
"	} else { // This means that there is a line intersection but not a ray intersection.\n"
"		out_distance = -1.0;\n"
"		return TRI_NO_INTERSECTION;\n"
"	}\n"
"}\n"
"\n"
"void main() {\n"
"	const int tile_index = int(gl_GlobalInvocationID.z);\n"
"\n"
"	const ivec2 tile_data = u_tile_data.data[tile_index];\n"
"	const int tri_count = (tile_data.y >> 4) & 0x7;\n"
"\n"
"	if (tri_count == 0) {\n"
"		return;\n"
"	}\n"
"\n"
"	const ivec2 pixel_pos_in_tile = ivec2(gl_GlobalInvocationID.xy);\n"
"\n"
"	const int tri_info_begin = tile_data.y >> 8;\n"
"	const int projection = tile_data.y & 0x3;\n"
"\n"
"	const int packed_cell_pos = tile_data.x;//u_tile_cell_positions.data[tile_index];\n"
"	const vec3 cell_pos_cells = vec3(\n"
"		packed_cell_pos & 0xff,\n"
"		(packed_cell_pos >> 8) & 0xff,\n"
"		(packed_cell_pos >> 16) & 0xff\n"
"	);\n"
"	const float cell_size_world = u_params.pixel_world_step * float(u_params.tile_size_pixels);\n"
"	const vec3 cell_origin_mesh = cell_size_world * cell_pos_cells;\n"
"\n"
"	// Choose a basis where Z is the axis we cast the ray. X and Y are lateral axes of the tile.\n"
"	const vec3 ray_dir = vec3(float(projection == 0), float(projection == 1), float(projection == 2));\n"
"	const vec3 dx = vec3(float(projection == 1 || projection == 2), 0.0, float(projection == 0));\n"
"	const vec3 dy = vec3(0.0, float(projection == 0 || projection == 2), float(projection == 1));\n"
"\n"
"	const vec2 pos_in_tile = u_params.pixel_world_step * vec2(pixel_pos_in_tile);\n"
"	const vec3 ray_origin_mesh = cell_origin_mesh\n"
"		 - 1.01 * ray_dir * cell_size_world\n"
"		 + pos_in_tile.x * dx + pos_in_tile.y * dy;\n"
"\n"
"	// Find closest hit triangle\n"
"	const float no_hit_distance = 999999.0;\n"
"	float nearest_hit_distance = no_hit_distance;\n"
"	int nearest_hit_tri_index = -1;\n"
"	for (int i = 0; i < tri_count; ++i) {\n"
"		const int tri_index = u_cell_tris.data[tri_info_begin + i];\n"
"		const int ii0 = tri_index * 3;\n"
"		\n"
"		const int i0 = u_indices.data[ii0];\n"
"		const int i1 = u_indices.data[ii0 + 1];\n"
"		const int i2 = u_indices.data[ii0 + 2];\n"
"\n"
"		const vec3 v0 = u_vertices.data[i0];\n"
"		const vec3 v1 = u_vertices.data[i1];\n"
"		const vec3 v2 = u_vertices.data[i2];\n"
"\n"
"		float hit_distance;\n"
"		const int intersection_result = ray_intersects_triangle(ray_origin_mesh, ray_dir, v0, v1, v2, hit_distance);\n"
"\n"
"		if (intersection_result == TRI_INTERSECTION && hit_distance < nearest_hit_distance) {\n"
"			nearest_hit_distance = hit_distance;\n"
"			nearest_hit_tri_index = tri_index;\n"
"		}\n"
"	}\n"
"\n"
"	const int index = pixel_pos_in_tile.x + pixel_pos_in_tile.y * u_params.tile_size_pixels \n"
"		+ tile_index * u_params.tile_size_pixels * u_params.tile_size_pixels;\n"
"\n"
"	if (nearest_hit_tri_index != -1) {\n"
"		const vec3 hit_pos_world = ray_origin_mesh + ray_dir * nearest_hit_distance + u_params.block_origin_world;\n"
"		u_hits.positions[index] = vec4(hit_pos_world, nearest_hit_tri_index);\n"
"	} else {\n"
"		u_hits.positions[index] = vec4(0.0, 0.0, 0.0, -1.0);\n"
"	}\n"
"}\n";
// clang-format on
